package wmarduino;

import Structures.*;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;


/**
 * Instancia y ejecuta las acciones para un caza recompenzas
 * @author Rodrigo
 * @author Alexandre
 * @author Gabriel
 * @author Jeremy
 */
public class BountyHunter extends Thread{
    
    private SLL _ltswhrASonVisitar;    // Lista de arduinos que el caza recompensas conoce que esta en el domain y puede visitar.
    private SLL _ltswhrAVisitados;    // Lista de arduinos que el caza recompensas conoce que esta en el domain y ya visito.
    private static String _HD;   //home Domain
    private String _CID;     //Numero que representa al cazarrecompensas;
    private String _FD;   // Dominio que esta visitando
    private Node _HR;   //home Region
    private Node _FR;   // region(nodo) en el que esta.
    private Node _TR;  // region(nodo) que debe visitar.    
    private int _points;  // points que "carga" el cazarrecompensas
    private String _NM;   // Nombre del Caza Recompensas dado por el usuario.
    private static Random randomGenerator = new Random();
    private boolean deadThread;
    private Domain graph;

 /**
  * Constructor que crea el bounty hunter.
  * @param pHR Region casa
  * @param pCID Identificador del cazarecompenzas
  * @param pFR Region Foranea
  * @param pHD Dominio casa
  * @param pGraph Grafo o dominio utilizado
  */
    public BountyHunter(String pHD,Node pHR, String pCID, Node pFR, Domain pGraph) {
        this._ltswhrASonVisitar = new SLL();
        this._ltswhrAVisitados = new SLL();
        this._HR = pHR;
        this._HD=pHD;
        this._CID = pCID;
        this._FR = pFR;
        this._points = 0;
        this.graph= pGraph;
        
    }

    // Setters and Getters.   
    
    /**
     * Devuelve la lista de arduinos
     * @return Lista de arduinos
     */
    public SLL getLtswhrASonVisitar() {
        return _ltswhrASonVisitar;
    }

    /**
     * Devuelve la lista de arduinos ya visitados
     * @return 
     */
    public SLL getLtswhrAVisitados() {
        return _ltswhrAVisitados;
    }
    
    /**
     * Obtiene el domino casa del  cazarrecompensas.
     * @return HD Un String que representa el identificador del dominio casa
     */
    public String getHD() {
        return _HD;
    }
    
    /**
     * Obtiene la region(nodo) casa del  cazarrecompensas.
     * @return HR Un String que representa el identificador de la region casa
     */
    public Node getHR() {
        return _HR;
    }
        
    /**
     * Retorna en numero el cual representa al cazarrecompensas. 
     * @return Un entero que representa el identificador del cazarecompenzas
     */
    public String getCID() {
        return _CID;
    }
    
    /**
     * Retorna el dominio que esta visitando el cazarrecompensas.
     * @return FD Un String que representa el identificador del dominio foráneo o dominio que está visitando en el momento
     */
    public String getFD() {
        return _FD;
    }
    
    /**
     * Actualiza el dominio que el cazarrecompensas visita.
     * @param pFD Identificador del dominio foráneo para establecer
     */
    public void setFD(String pFD) {
        this._FD = pFD;
    }
    
    /**
     * Retorna el nodo que el cazarrecompensas visita.
     * @return FR Un String que representa la región foránea o región que se está visitando en el momento
     */
    public Node getFR() {
        return _FR;
    }
    
    /**
     * Actualiza el nodo que el cazarrecompensas visita.
     * @param pFR Un String que representa la región foránea para establecer
     */
    public void setFR(Node pFR) {
        this._FR = pFR;
    }
    
    /**
     * Retorna los puntos que carga el cazarrecompensas
     * @return Entero que representa los puntos que carga el cazarecompenzas en el momento
     */
    public int getPoints() {
        return _points;
    }
    
    /**
     * Modofica los puntos que carga el cazarrecompensas
     * @param pPoints Entero para establecer los puntos
     */
    public void setPoints(int pPoints) {
        this._points += pPoints;
    }
    /**
     * Retorna la region(nodo) objetivo que posee el cazarrecompensas.
     * @return String que representa el identificador de la región que actualmente debe visitar el cazarecompenzas
     */
    public Node getTR() {
        return _TR;
    }
    
    /**
     * Modofica la region(nodo) objetivo que posee el cazarrecompensas.
     * @param pTR String que representa el identificador de la region que actualmente debe visitar el cazarecompenzas, para establecer
     */
    public void setTR(Node pTR) {
        this._TR = pTR;
    }

    /**
     * Metodo que obtiene el nombre del caza recompensas.
     * @return El nombre del caza recompensas dado por el usuario.
     */
    public String getNM() {
        return _NM;
    }

    /**
     * Metodo que modifica el nombre del caza recompensas.
     * @param NM darle un nombre al caza recomepenzas.
     */
    public void setNM(String NM) {
        this._NM = NM;
    }

 //   Metodos del bounty hunter.
    
    
    /**
     *Metodo que actualiza la lista de los arduinos que el bounty hunter conoce.
     * 
     */
    public void updatewhrArduinos() {
        SLL ltsDomainArduinos = Domain.getLtsArduinos();
        SLLNode tmpDomain;
        SLLNode tmpipdt = _ltswhrAVisitados.getFirst();
        boolean exist = false;

        for (tmpDomain = ltsDomainArduinos.getFirst(); tmpDomain != null; tmpDomain = tmpDomain.getSucc()) {
            while (tmpipdt.getElement() != null && !exist) {
                if (tmpDomain.getElement() == tmpipdt.getElement()) {
                    exist = true;
                } else {
                    tmpipdt = tmpipdt.getSucc();
                }
            }
            if (exist) {
                _ltswhrASonVisitar.insert((Node) tmpDomain.getElement());
            }
        }
    }

    /**
     * Metodo que hara el bounty hunter moverse hacia el siguiente arduino.
     */
    public void move() {
        int positionNodo = randomGenerator.nextInt(_ltswhrASonVisitar.getSize() - 1);
        if((_ltswhrASonVisitar.getSize())==(_ltswhrAVisitados.getSize())){
            deadThread=true;
        }
        if (_FR != _TR) {
            _ltswhrAVisitados.insert(_TR);
            ///////////////////FALTAN ASIGNACION DE PUNTOS ////////////////
            _FR = _TR;
        } else {
            if (positionNodo == 0) {
                _TR = (Node) _ltswhrASonVisitar.getFirst().getElement();
            }
            SLLNode tmp = _ltswhrASonVisitar.getFirst();
            for (int i = 0; i != positionNodo; i++)
            {
                tmp = tmp.getSucc();
            }
            _TR = (Node) tmp.getElement();
        }
    }    
    
    /**
     * Ejecuta el hilo para el caza recompensas.
     */
    @Override
    public void run(){
        while(!deadThread){
            try {
                Thread.sleep(graph.dijkstra(_FR, _TR));
                move();
    
            } catch (InterruptedException ex) {
                Logger.getLogger(BountyHunter.class.getName()).log(Level.SEVERE, null, ex);
            }
            
        } 
    }
}
